/*
//
//              INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license  agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in  accordance  with the terms of that agreement.
//    Copyright (c) 2007-2008 Intel Corporation. All Rights Reserved.
//
//
*/

#include "umc_defs.h"
#if defined(UMC_ENABLE_AVS_VIDEO_DECODER)

#include "umc_avs_dec_processing_unit_deb.h"

#include "umc_automatic_mutex.h"
#include "umc_mutex.h"

namespace UMC
{

AVSDebProcessingUnit::AVSDebProcessingUnit(void)
{

} // AVSDebProcessingUnit::AVSDebProcessingUnit(void)

AVSDebProcessingUnit::~AVSDebProcessingUnit(void)
{

} // AVSDebProcessingUnit::~AVSDebProcessingUnit(void)

bool AVSDebProcessingUnit::LoadJob(AVSListElement<AVSFrame> *pFrameList)
{
    eAVSPicStructure field = AVS_UPPER_FIELD;

    // run over frame list and find an unparsed slice
    while (pFrameList)
    {
        AVSListElement<AVSSlice> *pSlice;
        AVSPicture *pPic;

        // get current picture
        if (AVS_FRAME == pFrameList->m_picStructure)
        {
            pPic = pFrameList;
        }
        else
        {
            pPic = pFrameList->GetPicture(field);
        }

        // get slices from the frame
        pSlice = pPic->m_Slices.GetHead();

        // run over slice list and find an unparsed slice
        while (pSlice)
        {
            if ((false == pSlice->m_bError) &&
                (pSlice->m_bDebVacant) &&
                (pSlice->m_debCtx.MbIndex < pSlice->m_debCtx.MbLast) &&
                ((pSlice->m_recCtx.MbIndex - pSlice->m_debCtx.MbIndex >= pSlice->m_debCtx.MbWidth * 2) ||
                 (pSlice->m_recCtx.MbIndex == pSlice->m_recCtx.MbLast)) )
            {
                // this slice is uncomplete,
                // wrap it around and go work.

                m_deblocker.SetDeblockingContext(pSlice->m_debCtx);
                pSlice->m_bDebVacant = false;

                return true;
            }

            pSlice = pSlice->GetNext();
        }

        // get next frame only if both fields of the current were inspected
        if ((AVS_FRAME == pFrameList->m_picStructure) ||
            (AVS_LOWER_FIELD == field))
        {
            pFrameList = pFrameList->GetNext();
            field = AVS_UPPER_FIELD;
        }
        else
        {
            field = AVS_LOWER_FIELD;
        }
    }

    return false;

} // bool AVSDebProcessingUnit::LoadJob(AVSListElement<AVSFrame> *pFrameList)

Status AVSDebProcessingUnit::DoJob(void)
{
    // do deblocking manipulation
    switch (m_deblocker.GetDeblockingContext().m_pPicHeader->PictureType)
    {
    case AVS_I_PICTURE:
        m_deblocker.DeblockIMacroBlocksRow();
        break;

    case AVS_P_PICTURE:
        m_deblocker.DeblockPMacroBlocksRow();
        break;

    case AVS_B_PICTURE:
        m_deblocker.DeblockBMacroBlocksRow();
        break;
    default:
        break;
    };

    // finalize processed task
    UnloadJob();

    return UMC_ERR_NOT_ENOUGH_DATA;

} // Status AVSDebProcessingUnit::DoJob(void)

Status AVSDebProcessingUnit::HandleError(void)
{
    // adjust parameters
    UnloadJob();

    return UMC_ERR_NOT_ENOUGH_DATA;

} // Status AVSDebProcessingUnit::HandleError(void)

void AVSDebProcessingUnit::UnloadJob(void)
{
    AVSSlice *pSlice;

    pSlice = m_deblocker.GetDeblockingContext().m_pSlice;

    // reflect changes to the slice
    {
        AutomaticMutex guard(m_pGuard->ExtractHandle());

        pSlice->m_debCtx = m_deblocker.GetDeblockingContext();
        pSlice->m_bDebVacant = true;

        // move exhausted slice to other queue
        if (pSlice->m_debCtx.MbIndex == pSlice->m_debCtx.MbLast)
        {
            pSlice->m_pPic->MarkSliceAsDone(pSlice);
        }
    }

} // void AVSDebProcessingUnit::UnloadJob(void)

} // namespace UMC

#endif // defined(UMC_ENABLE_AVS_VIDEO_DECODER)
